package net.zjitc.filter;

import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import net.zjitc.entity.Manager;
import net.zjitc.security.IUserDetailService;
import net.zjitc.service.ManagerService;
import net.zjitc.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 毛钰深
 * @create 2022/1/24
 * 继承BasicAuthenticationFilter(认证器基本类,判断在登录认证器之后,因为不是登录访问,而是其他操作),用来获取请求头中的jwt信息,并且实现自动登录(即通过jwt来认证)
 */
//重写了构造器,所以无法使用注解来生成一个Bean对象,并且让Spring容器管理,在配置类中配置
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private IUserDetailService iUserDetailService;

    @Autowired
    private ManagerService managerService;

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //获取jwt
        String jwt=request.getHeader(jwtUtils.getHeader());
        //jwt为空,则说明请求是登录页的资源请求（白名单）或者非法访问，这里不做处理,后续security会自动处理，详见SecurityConfig的配置拦截规则
        //不带jwt token就不走此过滤器验证token，让它去匿名访问过滤器，看是否是白名单中的url，如果不是白名单中的url，就会抛异常，去登录页
        //判断jwt是否存在,不存在就直接放行跳过,交给后面的处理器(登录或者认证)处理
        if ((StrUtil.isBlankOrUndefined(jwt))){
            chain.doFilter(request,response);
            return;
        }

        //获取主体内容
        Claims claim = jwtUtils.getClaimByToken(jwt);
        if (claim==null){
            throw new JwtException("token异常,解析失败");
        }

        //判断token是否过期
        if (jwtUtils.isTokenExpired(claim)){
            throw new JwtException("token已过期");
        }

        //获取用户名
        String username = claim.getSubject();

        Manager manager = managerService.getByUsername(username);

        //获取用户的权限等信息
        //参数一是用户名,二是密码,现在使用的是token自动登录,所以是null,三是权限信息
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, iUserDetailService.getUserAuthority(manager));
        //通过获取上下文信息,使用token进行自动登录
        SecurityContextHolder.getContext().setAuthentication(token);
        //登录完成后,放行
        chain.doFilter(request,response);
    }


}
